
/* CONSTRAINTS, TRIGGERS, VIEWS y STORES PROCEDURES */

/* 
Punto 4 de los "Comentarios de la cátedra"
verifica que un empleado_no_profesional no pueda ser asignado a un area que no tiene el nivel de seguridad 
 */
CREATE FUNCTION CheckAccesoPosibleValido() RETURNS trigger AS '
BEGIN
  IF (SELECT 
        nivel_seguridad_id 
      FROM 
        area
      WHERE
        area_id = NEW.area_id) >
     (SELECT 
        nivel_seguridad_id
      FROM
        empleado_no_profesional
      WHERE
        empleado_id = NEW.empleado_id) THEN
    RAISE EXCEPTION ''Este empleado no profesional no tiene el nivel de seguridad para poder acceder a esta area.'';
  END IF;
  RETURN NEW;
END' LANGUAGE plpgsql;

CREATE TRIGGER AccesoPosibleValido
  BEFORE INSERT OR UPDATE ON empleado_no_profesional_acceso
  FOR EACH ROW
  EXECUTE PROCEDURE CheckAccesoPosibleValido();


/* 
Punto 5 de los "Comentarios de la cátedra"
Se eligió poner contraints en las tablas que representan una "jerarquia" que verifiquen que un insert en una tabla 
"hijo" coincida con el valor del discriminante en la tabla padre. 
En el modelo hay dos jerarquías

empleado: la columna discrimimante es "categoria" y puede tener los valor 0, 1 o 2
categoria = 0: El hijo va en la tabla "empleado_no_profesional"
categoria = 1: El hijo va en la tabla "empleado_jerarquico"
categoria = 2: El hijo va en la tabla "empleado_profesional"

empleado_profesional: la columna discrimimante es "tipo_profesional" y puede tener los valor 0 o 1
tipo_profesional = 0: El hijo va en la tabla "empleado_profesional_planta_permanente"
tipo_profesional = 1: El hijo va en la tabla "empleado_profesional_contratado"

*/

/* CONSTRAINT: empleado.categoria puede valer 0, 1 o 2 */
ALTER TABLE empleado ADD constraint CategoriaValida check(categoria >= 0 AND categoria <= 2);

/* CONSTRAINT: emploado_profesional.tipo_profesional puede valer 0 o 1 */
ALTER TABLE empleado_profesional ADD constraint TipoProfesionalValido check(tipo_profesional >= 0 AND tipo_profesional <= 1);

/* FUNCTION+TRIGGER: verifica que un empleado no profesional tenga el valor 0 en la empleado.categoria */
CREATE FUNCTION CheckEmpleadoNoProfesional() RETURNS trigger AS '
BEGIN
  IF (SELECT 
          categoria 
      FROM 
          empleado 
      WHERE 
          empleado_id = NEW.empleado_id
      ) != 0 THEN
    RAISE EXCEPTION ''Solo se puede insertar empleados no profesionales en empleado_no_profesional.'';
  END IF;
  RETURN NEW;    
END' LANGUAGE plpgsql;
    
CREATE TRIGGER EmpleadoNoProfesional
  BEFORE INSERT OR UPDATE ON empleado_no_profesional
  FOR EACH ROW
  EXECUTE PROCEDURE CheckEmpleadoNoProfesional();

/* FUNCTION+TRIGGER: verifica que un empleado jerarquico tenga el valor 1 en la empleado.categoria */
CREATE FUNCTION CheckEmpleadoJerarquico() RETURNS trigger AS '
BEGIN
  IF (SELECT
        categoria
      FROM
        empleado
      WHERE
        empleado_id = NEW.empleado_id
      ) != 1 THEN
    RAISE EXCEPTION ''Solo se puede agregar personal jerarquico a empleado_jerarquico.'';
  END IF;
  RETURN NEW;
END' LANGUAGE plpgsql;

CREATE TRIGGER EmpleadoJerarquico
  BEFORE INSERT OR UPDATE ON empleado_jerarquico
  FOR EACH ROW
  EXECUTE PROCEDURE CheckEmpleadoJerarquico();

/* FUNCTION+TRIGGER: verifica que un empleado profesional tenga el valor 2 en la empleado.categoria */
CREATE FUNCTION CheckEmpleadoProfesional() RETURNS trigger AS '
BEGIN
  IF (SELECT
        categoria
      FROM
        empleado
      WHERE
        empleado_id = NEW.empleado_id
      ) != 2 THEN
    RAISE EXCEPTION ''Solo se puede agregar personal profesional a empleado_profesional.'';
  END IF;
  RETURN NEW;
END' LANGUAGE plpgsql;

CREATE TRIGGER EmpleadoProfesional
  BEFORE INSERT OR UPDATE ON empleado_profesional
  FOR EACH ROW
  EXECUTE PROCEDURE CheckEmpleadoProfesional();

/* FUNCTION+TRIGGER: verifica que un empleado profesional contratado tenga el valor 1 en la empleado_profesional.tipo_profesional */
CREATE FUNCTION CheckProfesionalContratado() RETURNS trigger AS '
BEGIN
  IF (SELECT
        tipo_profesional
      FROM
        empleado_profesional
      WHERE
        empleado_id = NEW.empleado_id) != 1 THEN
    RAISE EXCEPTION ''Solo los profesionales contratados pueden ser agregados a empleado_profesional_contratado.'';
  END IF;
  RETURN NEW;
END' LANGUAGE plpgsql;

CREATE TRIGGER ProfesionalContratado
  BEFORE INSERT OR UPDATE ON empleado_profesional_contratado
  FOR EACH ROW
  EXECUTE PROCEDURE CheckProfesionalContratado();


/* FUNCTION+TRIGGER: verifica que un empleado profesional planta permantente tenga el valor 0 en la empleado_profesional.tipo_profesional */
CREATE FUNCTION CheckProfesionalPlantaPermanente() RETURNS trigger AS '
BEGIN
  IF (SELECT
        tipo_profesional
      FROM
        empleado_profesional
      WHERE
        empleado_id = NEW.empleado_id) != 0 THEN
    RAISE EXCEPTION ''Solo los profesionales de planta permanente pueden ser agregados a empleado_profesional_planta_permanente.'';
  END IF;
  RETURN NEW;
END' LANGUAGE plpgsql;

CREATE TRIGGER ProfesionalPlantaPermanente
  BEFORE INSERT OR UPDATE ON empleado_profesional_planta_permanente
  FOR EACH ROW
  EXECUTE PROCEDURE CheckProfesionalPlantaPermanente();


